const request = require('co-request');
const HttpStatus = require('http-status-codes');
const Joi = require('joi');

const API = require('../../config/API');
require('./device.model');
const ApplicationModel = require('mongoose').model('Application');
const DeviceValidation = require('./device.validation');


function* getPublicDevices() {
  try {
    const result = yield request(API.devices);

    this.body = { data: JSON.parse(result.body) };
  } catch (e) {
    this.throw(HttpStatus.INTERNAL_SERVER_ERROR, e);
  }
}

function* applyDevice() {
  // TODO: 对同一台机器的申请流程需要加锁等操作，否则有可能产生bug
  const { deviceID } = this.params;
  const { duration, deviceModel, localTime} = this.request.body;
  const userID = this.state.user.sub;
  const validation = Joi.validate({deviceID, duration, deviceModel, localTime}, DeviceValidation.applySchema);

  if (validation.error) {
    this.throw(HttpStatus.BAD_REQUEST, validation.error.details[0].message);
  }

  try {
    yield ApplicationModel.isUsed(deviceID, true, userID);
  } catch (e) {
    this.throw(HttpStatus.BAD_REQUEST, e.message);
  }

  const applyTime = Date.now();
  const newApplication = new ApplicationModel({ userID, deviceID, deviceModel, duration, applyTime });
  try {
    yield newApplication.save();
    this.status = HttpStatus.CREATED;
    let back = { data: newApplication.toJSON() };
    back.data.localTime = localTime;
    this.body = back;
  } catch (e) {
    this.throw(HttpStatus.INTERNAL_SERVER_ERROR, e.message);
  }
}

function* releaseDevice() {
  const { deviceID } = this.params;
  const userID = this.state.user.sub;

  const validation = Joi.validate({ deviceID }, DeviceValidation.deviceIDSchema);
  if (validation.error) {
    this.throw(HttpStatus.BAD_REQUEST, validation.error.details[0].message);
  }

  try {
    yield ApplicationModel.releaseDevice(deviceID, userID);
    yield request(`${API.releaseDevice}${deviceID}`);
    this.status = HttpStatus.OK;

  } catch (e) {
    this.throw(HttpStatus.INTERNAL_SERVER_ERROR, e.message);
  }
}

function* getPrivateDevices() {
  const userID = this.state.user.sub;
  try {
    const devices = yield ApplicationModel.getDevices(userID, true);
    this.body = { data: devices };
  } catch (e) {
    this.throw(HttpStatus.INTERNAL_SERVER_ERROR, e.message);
  }
}

function* isAvailableDevice() {
  const { deviceID } = this.params;
  const validation = Joi.validate({ deviceID}, DeviceValidation.deviceIDSchema);
  if (validation.error) {
    this.throw(HttpStatus.BAD_REQUEST, validation.error.details[0].message);
  }

  try {
    const userID = this.state.user.sub;
    yield ApplicationModel.isAvailable(deviceID, userID);
    this.body = { data: { isAvailable: true } };
  } catch (e) {
    this.body = { data: { isAvailable: false }, msg: e.message };
  }
}

function* isAllowApply () {
  try {
    const userID = this.state.user.sub;
    yield ApplicationModel.isAllowApply(userID);
    this.body = { data: { isAllow: true } };
  } catch (e) {
    this.body = { data: { isAllow: false }, msg: e.message };
  }
}


const deviceController = {
  getPublicDevices,
  getPrivateDevices,
  applyDevice,
  releaseDevice,
  isAvailableDevice,
  isAllowApply: isAllowApply,
};
module.exports = deviceController;
